﻿using System;
using System.Collections.Generic;
using System.Security;
using DotNetNuke.Entities.Modules;


namespace BigfootDNN.Mvc
{

    /// <summary>
    /// This is the base controller class from which all MVC controller must inherit
    /// </summary>
    public class BaseController
    {

        /// <summary>
        /// Holds the ModuleInfo object for the current module
        /// </summary>
        public ModuleInfo ModData { get { return Route.ModData; } }

        /// <summary>
        /// The current route being executed
        /// </summary>
        public RouteInfo Route { get; set; }

        /// <summary>
        /// Returns a new ActionResult for the View that matches the current action
        /// </summary>
        /// <returns>An action result object to be consumed by the route handler</returns>
        public ActionResult ViewResult()
        {
            return ViewResult(Route.Controller, Route.Action, null);
        }

        /// <summary>
        /// Returns a new ActionResult for the View that matches the current action
        /// </summary>
        /// <param name="data">Passes the data to be used as the View's model</param>
        /// <returns>An action result object to be consumed by the route handler</returns>
        public ActionResult ViewResult(object data)
        {
            return ViewResult(Route.Controller, Route.Action, data);
        }

        /// <summary>
        /// Returns a new ActionResult for the View specified but within the current controller
        /// </summary>
        /// <param name="viewName">Name of the view to return within the contorller view folder</param>
        /// <returns>An action result object to be consumed by the route handler</returns>
        public ActionResult ViewResult(string viewName)
        {
            return ViewResult(Route.Controller, viewName, null);
        }


        /// <summary>
        /// Returns a new ActionResult for the View specified but within the current controller
        /// </summary>
        /// <param name="viewName">Name of the view to return within the current contorller view folder</param>
        /// <param name="data">Passes the data to be used as the View's model</param>
        /// <returns>An action result object to be consumed by the route handler</returns>
        public ActionResult ViewResult(string viewName, object data)
        {
            return ViewResult(Route.Controller, viewName, data);
        }

        /// <summary>
        /// Returns a new ActionResult for the action and controller specified
        /// </summary>
        /// <param name="Action">Name of the action within the controller</param>
        /// <param name="Controller">Name of the controller that contains the action</param>
        /// <param name="data">Passes the data to be used as the View's model</param>
        /// <returns>An action result object to be consumed by the route handler</returns>
        public ActionResult ViewResult(string Controller, string Action, object data)
        {
            Route.Controller = Controller;
            Route.Action = Action;
            return new ActionResult(ActionResult.ActionTypeEnum.View, Route, data);
        }

        /// <summary>
        /// Retursn a new ActionResult with json data to be returned to the client
        /// </summary>
        /// <param name="jsondata">JSON formatted string to return to client</param>
        /// <returns>An ActionResult object to be consumed by the route handler</returns>
        public ActionResult JsonResult(string jsondata)
        {
            return new ActionResult(ActionResult.ActionTypeEnum.Json, Route, jsondata);
        }

        /// <summary>
        /// Retursn a new ActionResult with a literal string to be returned to the client
        /// </summary>
        /// <param name="data">String to return to the client</param>
        /// <returns>An ActionResult object to be consumed by the route handler</returns>
        public ActionResult LiteralResult(string data)
        {
            return new ActionResult(ActionResult.ActionTypeEnum.Literal, Route, data);
        }

        /// <summary>
        /// Redirects the user to another action within this controller
        /// </summary>
        /// <param name="actionName">The name of the action to redirect to</param>
        /// <returns>And action result to be consumed by the route handler</returns>
        public ActionResult RedirectToAction(string actionName)
        {
            //return RouteHelper.ExecuteAction(DnnApp.CurrentRoute.Controller, actionName);
            Route.Action = actionName;
            return RouteHelper.ExecuteAction(Route);
        }

        /// <summary>
        /// Redirects the user to another action within a different controller
        /// </summary>
        /// <param name="actionName">The name of the action to redirect to</param>
        /// <param name="controllerName">The name of the controller that contains the action</param>
        /// <returns>And action result to be consumed by the route handler</returns>
        public ActionResult RedirectToAction(string controllerName, string actionName)
        {
            Route.Controller = controllerName;
            Route.Action = actionName;
            return RouteHelper.ExecuteAction(Route);
        }

        /// <summary>
        /// Determines weather the current request is a POST
        /// </summary>
        public bool IsPOST { get { return Route.App.Request.RequestType == "POST"; } }

        /// <summary>
        /// Determines weather the current request is a GET
        /// </summary>
        public bool IsGET { get { return Route.App.Request.RequestType == "GET"; } }

        /// <summary>
        /// Determines weather the request is authenticated
        /// </summary>
        public bool IsAuthenticated
        {
            get { return Route.App.Request.IsAuthenticated; }
        }

        /// <summary>
        /// Checkes weather the current request is authenticated and throws an exception if it is not
        /// </summary>
        public void AuthenticatedOnly()
        {
            if (IsAuthenticated == false)
            {
                throw new SecurityException("Must be logged in to perform this action!");
            }
        }

        /// <summary>
        /// Makes sure the request is a post. Throws an exception if it is not
        /// </summary>
        public void POSTRequestOnly()
        {
            if (IsPOST == false)
            {
                throw new ApplicationException("Invalid GET request!");
            }
        }

        /// <summary>
        /// Makes sure the request is a get. Throws an exception if it is not
        /// </summary>
        public void GETRequestOnly()
        {
            if (IsGET == false)
            {
                throw new  ApplicationException("Invalid POST request!");
            }
        }

        /// <summary>
        /// Gets a parameter value from the request. Weather it be in the querystring or form collection. and throws an error if it is not found
        /// </summary>
        /// <param name="name">The parameter name</param>
        /// <returns>A string value for the specified parameter</returns>
        public string GetValueOrError(string name) { return Route.App.Values.GetValueOrError(name); }

        /// <summary>
        /// Gets a parameter value from the request. Weather it be in the querystring or form collection. and throws an error if it is not found
        /// </summary>
        /// <param name="name">The parameter name</param>
        /// <returns>A integer value for the specified parameter</returns>
        public int GetValueOrErrorAsInt(string name) { return Route.App.Values.GetValueOrErrorAsInt(name); }

        /// <summary>
        /// Gets a parameter value from the request. Weather it be in the querystring or form collection. and throws an error if it is not found
        /// </summary>
        /// <param name="name">The parameter name</param>
        /// <returns>A Double value for the specified parameter</returns>
        public double GetValueOrErrorAsDouble(string name) { return Route.App.Values.GetValueOrErrorAsDouble(name); }

        /// <summary>
        /// Gets a parameter value from the request. Weather it be in the querystring or form collection. and throws an error if it is not found
        /// </summary>
        /// <param name="name">The parameter name</param>
        /// <returns>A Date value for the specified parameter</returns>
        public DateTime GetValueOrErrorAsDate(string name) { return Route.App.Values.GetValueOrErrorAsDate(name); }

        /// <summary>
        /// Gets a parameter value from the request. Weather it be in the querystring or form collection as a nullable object. It is null when not found
        /// </summary>
        /// <param name="key">The parameter name</param>
        /// <returns>A nullable integer value for the parameter. It is null if the parameter was not found</returns>
        public int? GetInt(string key) { return Route.App.Values.GetInt(key); }

        /// <summary>
        /// Gets a parameter value from the request. Weather it be in the querystring or form collection as an array of integers
        /// </summary>
        /// <param name="key">The parameter name that contians the list of integers separated by either a comman or a semicolon</param>
        /// <returns>The list of integers</returns>
        public List<int> GetIntArray(string key) { return Route.App.Values.GetIntArray(key); }

        /// <summary>
        /// Gets a parameter value from the request. Weather it be in the querystring or form collection as a nullable object. It is null when not found
        /// </summary>
        /// <param name="key">The parameter name</param>
        /// <returns>A nullable decimal value for the parameter. It is null if the parameter was not found</returns>
        public decimal? GetDecimal(string key) { return Route.App.Values.GetDecimal(key); }

        /// <summary>
        /// Gets a parameter value from the request. Weather it be in the querystring or form collection as a nullable object. It is null when not found
        /// </summary>
        /// <param name="key">The parameter name</param>
        /// <returns>A nullable double value for the parameter. It is null if the parameter was not found</returns>
        public double? GetDouble(string key) { return Route.App.Values.GetDouble(key); }

        /// <summary>
        /// Gets a parameter value from the request. Weather it be in the querystring or form collection as a nullable object. It is null when not found
        /// </summary>
        /// <param name="key">The parameter name</param>
        /// <returns>A nullable date value for the parameter. It is null if the parameter was not found</returns>
        public DateTime? GetDate(string key) { return Route.App.Values.GetDate(key); }

        /// <summary>
        /// Gets a parameter value from the request. Weather it be in the querystring or form collection as a boolean.
        /// </summary>
        /// <param name="key">The parameter name</param>
        /// <returns>It returns true if the value of the parameter is true, on, yes, or 1 othewise returns false</returns>
        public bool GetBool(string key) { return Route.App.Values.GetBool(key); }

        private UrlHelper _url;
        /// <summary>
        /// Creates a new instance of the UrlHelper class to help you create urls
        /// </summary>
        public UrlHelper Url
        {
            get { return _url ?? (_url = new UrlHelper(Route)); }
        } 

    }

}
